#include <iostream>
#include <cstdint>
#include <string>
using namespace std;

#include <boost/optional.hpp>
#include <boost/optional/optional_io.hpp>

struct test
{
    test(const char *sz)
        : _s(sz)
    {
        cout << "test(const char* sz)" << endl;
    }

    test(const std::string &s)
        : _s(s)
    {
        cout << "test(const std::string& s)" << endl;
    }

    test(std::string &&s)
        : _s(std::move(s))
    {
        cout << "test(std::string&& s)" << endl;
    }

    test(const test &other)
        : _s(other._s)
    {
        cout << "test(const test& other)" << endl;
    }

    test(test &&other) noexcept
        : _s(std::move(other._s))
    {
        cout << "test(test&& other)" << endl;
    }

    test &operator+=(const char *sz)
    {
        cout << "test& operator + (const char* sz)" << endl;
        _s += sz;
        return *this;
    }

    test &operator+=(const std::string &s)
    {
        cout << "test& operator + (const std::string& s)" << endl;
        _s += s;
        return *this;
    }

    test &operator+=(std::string &&s)
    {
        cout << "test& operator + (std::string&& s)" << endl;
        _s += s;
        return *this;
    }

    friend std::ostream &operator<<(std::ostream &os, const test &t)
    {
        os << t._s;
        return os;
    }

    std::string _s;
};

boost::optional<test &> foo(test &t)
{
    return boost::optional<test &>(t);
}

int main(int argc, char *argv[])
{
    test t("hello");
    auto i = foo(t);
    if (!i)
    {
        cout << "!i" << endl;
        return 0;
    }
    *i += " optional";
    cout << i << endl;
    return 0;
}
